<?php

require_once('lib/Yubico.php'); 

/**
 * Yubikey Authentication Plugin
 *
 * This plugin enables Yubikey authentication within Roundcubemail against the Yubikey web service API.
 *
 * @version 0.1
 * @author Oliver Martin <mail@olimartin.de> (based on the patch by dirkm)
 *
 * Yubikey Authentication Plugin
 * Copyright (C) 2009  Oliver Martin
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
 *
 */
class yubikey_auth extends rcube_plugin
{
    function init()
    {
		$this->load_config();
		
        $this->add_texts('localization/', false);

        $this->add_hook('user_preferences', array($this, 'settings_table'));
        $this->add_hook('save_preferences', array($this, 'save_prefs'));
        $this->add_hook('template_object_loginform', array($this, 'html_output'));
        $this->add_hook('login_after', array($this, 'login_after'));
    }

    function html_output($p)
    {
        $use_yubikey_value = rcmail::get_instance()->config->get('yubikey');
        
        if (isset($use_yubikey_value) && $use_yubikey_value == 1) {
            $table = new html_table(array('cols' => 2));
            $table->add('title', html::label('rcmloginyubikey', Q($this->gettext('yubikey'))));

            $input = new html_inputfield(array('name' => '_yubikey', 'id' => 'rcmloginyubikey', 'size' => 30, 'autocomplete' => "off"));
            $table->add(null, $input->show(get_input_value('_yubikey', RCUBE_INPUT_POST)));
            
            $p['content'] .= $table->show();
        }

        return $p;
    }

    function login_after($args)
    {
        $use_yubikey_value = rcmail::get_instance()->config->get('yubikey');
        if (!isset($use_yubikey_value) || $use_yubikey_value == 0) {
            return $args;
        }

        $yubkey_required = rcmail::get_instance()->config->get('yubikey_required');
    
        if (isset($yubkey_required) && $yubkey_required == 1) {
            $yubikey_otp = get_input_value('_yubikey', RCUBE_INPUT_POST);
            $yubikey_id = rcmail::get_instance()->config->get('yubikey_id');
        
            // make sure that there is a Yubikey ID in the user's prefs
            // and that it matches the first 12 characters of the OTP
            if (empty($yubikey_id) || substr($yubikey_otp, 0, 12) != $yubikey_id) {
                // Yubikey auth failed, back to login prompt
                rcmail::get_instance()->logout_actions();
                rcmail::get_instance()->kill_session();
            } 
            else {
                // Check the OTP against Yubikey webservice
                $yubi = &new Auth_Yubico(rcmail::get_instance()->config->get('yubikey_api_id'), rcmail::get_instance()->config->get('yubikey_api_key'));
                $auth = $yubi->verify($yubikey_otp);
      
                if (PEAR::isError($auth)) {
                    // Yubikey auth failed, back to login prompt
                    rcmail::get_instance()->logout_actions();
                    rcmail::get_instance()->kill_session();
                }
            }
        }

        return $args;
    }

    function settings_table($args)
    {
        // add config options to the server config panel
        if ($args['section'] == 'server') {
            // check if Yubikey is enabled
            $use_yubikey_value = rcmail::get_instance()->config->get('yubikey');

            if (isset($use_yubikey_value) && $use_yubikey_value == 1) {
                // add checkbox to enable/disable Yubikey auth for the current user
                $checked = rcmail::get_instance()->config->get('yubikey_required');
                $checked = ( isset($checked) && $checked == 1 ) ? 1 : 0;
                
                $chk_yubikey = new html_checkbox(array('name' => '_yubikey_required', 'id' => 'rcmfd_yubikey_required', 'value' => $checked));
                $args['table']->add('title', html::label('rcmfd_yubikey_required', Q($this->gettext('yubikeyrequired'))));
                if ( $checked == 1 ) {
                    $args['table']->add(null, $chk_yubikey->show(1));
                } 
                else {
                    $args['table']->add(null, $chk_yubikey->show());
                }

                // add inputfield for the Yubikey id
                $input_yubikey_id = new html_inputfield(array('name' => '_yubikey_id', 'id' => 'rcmfd_yubikey_id', 'size' => 10));
                $args['table']->add('title', html::label('rcmfd_yubikey_id', Q($this->gettext('yubikeyid'))));
                $args['table']->add(null, $input_yubikey_id->show(rcmail::get_instance()->config->get('yubikey_id')));
            }
        }

        return $args;
    }

    function save_prefs($args)
    {
        $use_yubikey_value = rcmail::get_instance()->config->get('yubikey');
        if (isset($use_yubikey_value) && $use_yubikey_value == 1) {
            $args['prefs']['yubikey_required'] = isset($_POST['_yubikey_required']) ? true : false;
            $args['prefs']['yubikey_id'] = $_POST['_yubikey_id'];
        }

        return $args;
    }
}